// (function(){

	(function()
	{
		phnq = typeof(phnq)=="undefined"?{}:phnq;

		//phnq.http = phnq.createObject("http");

		var EVAL_BODY = 0;
		var SKIP_BODY = 1;
		var EVAL_BODY_AGAIN = 2;
		var templates = {};
		var tags = {};
		var nextPhnqId = 0;
		
		var tagFooterBuff = [];
		tagFooterBuff.push("this.doStartTag = (typeof(doStartTag) == \"function\" ? doStartTag : null);");
		tagFooterBuff.push("this.doEndTag = (typeof(doEndTag) == \"function\" ? doEndTag : null);");
		tagFooterBuff.push("this.doAfterBody = (typeof(doAfterBody) == \"function\" ? doAfterBody : null);");
		tagFooterBuff.push("this.reset = (typeof(reset) == \"function\" ? reset : null);");
		var tagFooter = tagFooterBuff.join("");
		
		var tagCtx =
		{
			getAttribute: function(name)
			{
				var val = this.attrs["_"+name];
				if(typeof(val) == "undefined")
					return null;
		
				if(typeof(val)=="string" && !isNaN(val))
				{
					if(val.match(/false/i))
						val = false;
					else if(val.match(/true/i))
						val = true;
					else if(val.match(/\./))
						val = parseFloat(val);
					else
				 		val = parseInt(val, 10);
				}
		
				return val;
			},
		
			expose: function(n, v)
			{
				this.exposed[n] = v;
			}
		};

		var evalTag = function(type, attrs, parentTag, writeFn, bodyFn)
		{
			var tagFn = tags[type];
			var tp = tagFn.pool;
		
			var tag = tagFn.pool.length>0?tp.pop():new tagFn();
			var dst = tag.doStartTag;
			var dab = tag.doAfterBody;
			var det = tag.doEndTag;
		
			tag.parentTag = parentTag;
			tag.params = {};
		
			tagCtx.attrs = attrs;
			tagCtx.write = writeFn;
			// tagCtx.exposed = {"_tag": tag};
			tagCtx.exposed = {};
		
			if(dst==null || dst(tagCtx)!=SKIP_BODY)
			{
				if(bodyFn)
				{
					do
					{
						var args = [];
						for(n in tagCtx.exposed)
						{
							args.push(n);
							args.push(tagCtx.exposed[n]);
						}
		
						bodyFn.apply(null, args);
					}
					while(dab && dab(tagCtx)==EVAL_BODY_AGAIN);
				}
			}
		
			if(det)
				det(tagCtx);
		
			if(tag.reset)
				tag.reset();
		
			tp.push(tag);
		};

		phnq.runtime =
		{
			eval: function(objCode)
			{
				var result = [];
		
				var _ = function(str)
				{
					result.push(str);
				};
		
				var _t = evalTag;
				var _tag = null;
		
				var _expArgs = function(args)
				{
					var buff = [];
					// var len = args.length;
					// for(var i=0; i<len; i+=2)
					// {
					// 	buff.push("var ");
					// 	buff.push(args[i]);
					// 	buff.push("=");
					// 	buff.push("arguments["+(i+1)+"];");
					// }
					return buff.join("");
				};
		
				// client
				if(objCode)
					eval(objCode);
		
				// server
				tags[0] = function(parentTag)
				{
					this.type="org.phnq.phnqlets.forEach";
					var start;
					var end;
					var step;
					var items;
					var varName;
					var i;
		
					function doStartTag(ctx)
					{
						start = ctx.getAttribute("start") || 0;
						end = ctx.getAttribute("end");
						step = ctx.getAttribute("step") || 1;
						items = ctx.getAttribute("items");
		
						i = start;
		
						if(items)
						{
							if(!(items instanceof Array))
							{
								switch(typeof(items))
								{
									case "string":
									{
										items = items.split(",");
										break;
									}
									case "object":
									{
										var obj = items;
										items = [];
										for(k in obj)
										{
											items.push(k);
										}
										break;
									}
								}
							}
							end = items.length - 1;
		
							if(items.length == 0)
								return SKIP_BODY;
						}
						else
						{
							if(i > end)
								return SKIP_BODY;
						}
		
		
						varName = ctx.getAttribute("var");
						if(varName)
							ctx.expose(varName, items ? items[i] : i);
					}
		
					function doAfterBody(ctx)
					{
						if(i < end)
						{
							i += step;
		
							if(varName)
								ctx.expose(varName, items ? items[i] : i);
		
							return EVAL_BODY_AGAIN;
						}
					}
					
					eval(tagFooter);
				};
				
				tags[0].pool=[];
				
				templates[0] = function(params)
				{
					_("<html class=\"test.ForEachTest\"><head></head><body><table border=\"1\">");
					_t(0, {_var:"row",_start:"1",_end:"100"}, _tag, _, function()
					{
						var row = arguments[1];
						if(arguments.length)eval(_expArgs(arguments));
						_("<tr><td>"+(row)+"</td>");
						_t(0,{_var:"col",_start:"1",_end:"10"},_tag,_,function()
						{
							var col = arguments[1];
							if(arguments.length)eval(_expArgs(arguments));
							_("<td>("+(row)+","+(col)+")");
							_t(0,{_var:"data",_start:"1",_end:"10"},_tag,_,function()
							{
								var data = arguments[1];
								if(arguments.length)eval(_expArgs(arguments));
								_("-"+(data)+"");
							});
							
							_("</td>");
						});
						
						_("</tr>");
					});
		
					_("</table></body></html>");
				};
		
				templates[0]({});
		
				return result.join("");
			}
		};
		return phnq.runtime.eval();
	})();


// })();
